package com.android.readcard.utils;


import com.android.readcard.server.BLEService;
import com.android.readcard.server.CommandItem;
import com.android.readcard.server.NFCReaderService;
import com.android.readcard.server.USBHIDService;
import com.android.readcard.server.UartService;
import com.android.readcard.utils.djlm.DJLMReader3.reader.HexUtil;
import com.android.readcard.utils.djlm.SIMCard;
import com.android.readcard.utils.djlm.TempCache;

import java.io.IOException;
import java.util.Arrays;


/**
 * Created by Administrator on 2017/3/9.
 */

//设备数据读写类(蓝牙或NFC)
public class CardDeviceIO {
    private BLEService mBLEService = null;
    private USBHIDService mUSBHIDService = null;
    private NFCReaderService mNFCReaderService = null;
    private int m_nDeviceType = 0;
    private TempCache tempCache = new TempCache();
    public static final int DEVICETYPE_BLE = 0;
    public static final int DEVICETYPE_NFC = 1;
    public static final int DEVICETYPE_OTG = 2;
    private boolean m_bNotTry = false;
    static CardDeviceIO m_CardDeviceIO = null;

    public static CardDeviceIO GetCardDeviceIO() {
        if (m_CardDeviceIO == null)
            m_CardDeviceIO = new CardDeviceIO();
        return m_CardDeviceIO;
    }

    CardDeviceIO() {
    }

    /*
    初始化外部设备
     */
    public boolean InitDevice(BLEService bleService, USBHIDService uSBHIDService, NFCReaderService nfcReaderService, int nDeviceType) {

        LogUtils.e("测试","bleService="+bleService+" uSBHIDService="+uSBHIDService+" nfcReaderService="+nfcReaderService+" nDeviceType="+nDeviceType);

        boolean bRet = true;
        if (bleService != null)
            mBLEService = bleService;
        if (mBLEService != null)
            mBLEService.SetSilence(true);
        if (uSBHIDService != null)
            mUSBHIDService = uSBHIDService;
        if (nfcReaderService != null)
            mNFCReaderService = nfcReaderService;
        m_nDeviceType = nDeviceType;
        if (m_nDeviceType == CardDeviceIO.DEVICETYPE_BLE) {
            mBLEService.SetSilence(true);
            try {
                bRet = SIMCard.BLEFast(mBLEService, true);
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }
        InitForStartTrans();
        return bRet;
    }

    public void UninitDevice(boolean bDisconnect) {
        if (mBLEService != null) {
            mBLEService.SetSilence(false);
            if (bDisconnect)
                mBLEService.disconnect();
        }


    }

    /*
    获取设备序列号
     */
    String GetDeviceSN() {
        String strCientSN = "";
        if (m_nDeviceType == DEVICETYPE_BLE)
            strCientSN = mBLEService.mBluetoothDeviceAddress;
        return strCientSN;
    }

    String GetDeviceVer() {
        String strVer = "";
        if (m_nDeviceType == DEVICETYPE_BLE) {
            try {
                strVer = SIMCard.GetVer(mBLEService);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return strVer;
    }

    String GetDeviceType() {
        if (m_nDeviceType == DEVICETYPE_NFC) {
            return "NFC";
        } else if (m_nDeviceType == DEVICETYPE_BLE) {
            return "BLE";
        } else if (m_nDeviceType == DEVICETYPE_OTG) {
            return "OTG";
        } else {
            return "UNKNOW";
        }
    }

    /*
    蜂鸣器发声
     */
    void Beep() {
        if (m_nDeviceType == DEVICETYPE_BLE) {
            try {
                SIMCard.Beep(mBLEService);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**网络传输模块或者加速缓冲器会调用此接口来完成设备操作*/

    byte[] DeviceIOPort(byte[] query, int nTimeout) throws IOException {
        if (query != null)
            query = CommandItem.QueryStrigToBytes(query, query.length);
        /////////////////////////////////////////////////
        byte[] Ret = null;
        {
            Ret = DeviceIOPortBinary(query, nTimeout);
            //Ret = mCardDeviceIO.DeviceIOPort(Query, 0);
        }
        if (Ret != null)
            Ret = CommandItem.ResponseBytesToString(Ret, Ret.length);
        return Ret;
    }

    byte[] DeviceIOPortBinary(byte[] query, int nTimeout) throws IOException {
        byte[] ret = null;
        ///////////////////////////////////////
        {
            if (m_nDeviceType == DEVICETYPE_NFC) {
                byte[] retData = new byte[256];
                int nRetLen = 0;
                if (query != null) {
                    nRetLen = mNFCReaderService.NFCTrans(query, retData);
                    if (nRetLen >= 0)
                        ret = Arrays.copyOf(retData, nRetLen);
                }
            } else if (m_nDeviceType == DEVICETYPE_BLE) {
                /*
                ret = tempCache.FilterSameQuery(query);
                if (ret != null) {
                    tempCache.ResetCache();
                    return ret;
                }
                */
                ret = BLETrans(query);
                if (query != null && ret != null) {
                    tempCache.RecordQueryRespone(query, ret);
                    ret = tempCache.FixResponse(query, ret);
                }
            } else if (m_nDeviceType == DEVICETYPE_OTG) {
                if (query != null)
                    ret = mUSBHIDService.USBIDioAccess(query, query.length);
            }
        }
        //////////////////////////////////////
        return ret;
    }

    void DeviceIOOut(byte[] query) {
    }

    byte[] DeviceIOIn(int nTimeout) {
        return null;
    }

    ////////////////////////////////////////////////////////////////////
    //是否接着获取上次未能及时返回的剩余数据
    boolean m_bWaiteResponse = false;
    /*
    初始化设备数据传输
    */

    void InitForStartTrans() {
        if (mBLEService != null)
            mBLEService.SetSilence(true);
        ResetCache();
    }

    boolean IsDeviceOK() {
        if (m_nDeviceType == DEVICETYPE_BLE) {
            if (mBLEService.mConnectionState == UartService.STATE_DISCONNECTED)
                return false;
        }
        return true;
    }

    /*
    通过蓝与牙卡片通讯
     */
    byte[] BLETrans(byte[] Query) throws IOException {
        byte[] Ret = null;
        if (Query != null) {
            int nWaiteTime = 50;
            System.out.println("BLE send:" + HexUtil.bytesToHexString(Query));
            for (int i = 0; i < 5 && Ret == null; i++) {
                if (i > 0)
                    System.out.println("try " + i);
                //Query = CommandItem.QueryStrigToBytes(Query);
                if (m_bNotTry && i > 0)
                    Ret = SendBLEAndRead(null, nWaiteTime);
                else
                    Ret = SendBLEAndRead(Query, nWaiteTime);
                //Ret = CommandItem.ResponseBytesToString(Ret);
                //if (i == 0)
                {
                    if (Ret != null) {
                        Ret = tempCache.FilterCrossResponse(Query, Ret);
                        if (i > 0 && Ret == null) {
                            m_bNotTry = true;
                            System.out.println("Into No try Mode! ");
                        }
                    }
                }
                tempCache.RecordQueryRespone(Query, Ret);
                //nWaiteTime += 10;
            }
        } else if (m_bWaiteResponse) {
            //System.out.println("waite 1");
            Ret = SendBLEAndRead(null, 0);
            //Ret = CommandItem.ResponseBytesToString(Ret);
            Ret = tempCache.FilterCrossResponse(m_bleLastSendInnner, Ret);
        }
        m_bWaiteResponse = (Ret == null);
        return Ret;
    }

    void ResetCache() {
        m_bWaiteResponse = false;
        try {
            mBLEService.GetLastNotification(0);
        } catch (IOException e) {
            e.printStackTrace();
        }
        m_bleLastSendInnner = null;
    }

    byte[] m_bleLastSendInnner;
    long m_nSendTick = 0;
    long m_nRecvTick = 0;

    /*
    通过蓝牙服务与卡片通讯
     */
    byte[] SendBLEAndRead(byte[] query, int nOverTime) throws IOException {
        long nBeginTime = System.currentTimeMillis();
        byte[] ret = mBLEService.GetLastNotification(0);
        if (query != null) {
            if (!Arrays.equals(query, m_bleLastSendInnner) || ret == null) {
                ret = null;
                m_bleLastSendInnner = query;
                if (m_nRecvTick + 3 > System.currentTimeMillis()) {
                    try {
                        Thread.sleep(3);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                m_nSendTick = System.currentTimeMillis();
                if (!mBLEService.writeRXCharacteristic(query)) {
                }
            }
        }

        if (ret == null) {
            ret = mBLEService.GetLastNotification(nOverTime);
            if (ret != null)
                m_nRecvTick = System.currentTimeMillis();
        }
        ////////////////////////////////////////////////////////////////////////
        if (ret != null)
            System.out.println("BLE rev:(" + (System.currentTimeMillis() - nBeginTime) + ")" + HexUtil.bytesToHexString(ret));
        return ret;
    }
}
